// Perspective
// (c) jimon game studio

#include "CPerspective_Game.h"
#include "IProfiler.h"
#include "ISystem.h"
#include "ILogManager.h"
#include "IVariables.h"
#include "jeEngineController.h"
#include "jeSpriteFrameAnimator.h"
#include "jeRegisterObjects.h"

#include "IFpsCounter.h"
#include "IAnimator.h"

#include "IJEDManager.h"

namespace je
{
	namespace scene
	{
		class TestAnim:public IAnimator
		{
		protected:
		public:
			f32 Angle;

			TestAnim()
				:IAnimator("TestAnim"),Angle(0.0f)
			{
			}

			~TestAnim()
			{
			}

			//! On Update
			void OnUpdate()
			{
				Angle+=0.02f*JEDT32;
				ParentNode->SetPosition(jeVector3df(sin(Angle)*1.5f,sin(Angle),cos(Angle)*2));

				//f32 TA = Angle + 6.0f * je::jeDegToRad;
				//ParentNode->SetPosition(jeVector3df(sin(TA)*1.5f,sin(TA),cos(TA)*2));
				IAnimator::OnUpdate();
			}

			//! Get Animators Type Name
			jeStringc GetAnimatorTypeName()
			{
				return "TestAnim";
			}

		};
	}

	void PrepareAndSaveTestFont()
	{
		core::jeJED_DataBlock * Root = core::GetJEDManager()->CreateDataBlock(core::JEDDBT_NULL);
		Root->SetName("RootBlock");

		core::jeJED_BitmapFontBlock * Font = static_cast<core::jeJED_BitmapFontBlock*>(core::GetJEDManager()->CreateDataBlock(core::JEDDBT_BITMAPFONT));
		Font->SetName("Font");

		Font->SetFontImageName(L"DefaultFont");
		Font->SetFontSize(8);

		f32 Koef = 16.0f / 256.0f;
		f32 KoefX = 15.0f / 256.0f;
		f32 KoefY = 13.0f / 256.0f;
		f32 KoefD = 1.0f / 256.0f;
		
		for(u8 Y=0;Y<16;Y++)
			for(u8 X=0;X<16;X++)
			{
				core::jeJED_BitmapFontBlock::FontChar * TempChar = NULL;
				JENEW(TempChar,core::jeJED_BitmapFontBlock::FontChar)

				TempChar->Code = X+Y*16;
				f32 BaseX = X*Koef;
				f32 BaseY = Y*Koef;
				TempChar->U1 = BaseX;
				TempChar->U2 = BaseX+KoefX;
				TempChar->V1 = BaseY;
				TempChar->V2 = BaseY+KoefY;
				TempChar->ShiftX = 0.0f;
				TempChar->ShiftY = 0.0f;
				TempChar->SizeX = 15.0f;
				TempChar->SizeY = 13.0f;
				TempChar->CharShift = 0.0f;

				Font->GetCharsList().push_back(TempChar);
			}

		core::jeJED_BitmapFontBlock::FontCharListType::Iterator Iter = Font->GetCharsList().begin();

		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 00.0f;
		(*Iter++)->CharShift = 03.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 02.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 10.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 10.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 02.0f;
		(*Iter++)->CharShift = 03.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 02.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 02.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 09.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 15.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 02.0f;
		(*Iter++)->CharShift = 02.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 10.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 10.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 10.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 03.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 10.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 10.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 04.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 10.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 10.0f;
		(*Iter++)->CharShift = 11.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 10.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 09.0f;
		(*Iter++)->CharShift = 07.0f;
		(*Iter++)->CharShift = 08.0f;
		(*Iter++)->CharShift = 06.0f;
		(*Iter++)->CharShift = 05.0f;
		(*Iter++)->CharShift = 09.0f;
		(*Iter++)->CharShift = 06.0f;

		Iter = Font->GetCharsList().begin();


		for(u8 Y=0;Y<16;Y++)
			for(u8 X=0;X<16;X++)
			{
				core::jeJED_BitmapFontBlock::FontChar * TempChar = *Iter;

				if(TempChar->CharShift>0)
				{
					TempChar->U2 += KoefD * TempChar->CharShift - KoefX;
					TempChar->SizeX = TempChar->CharShift;
					TempChar->CharShift = 0.0f;

					JELOG(jeStringc(TempChar->Code)+jeStringc(" - ")+jeStringc(TempChar->SizeX))
				}

				Iter++;
			}

		core::jeJED_BitmapFontBlock::FontKerning * TempKerning = NULL;
		JENEW(TempKerning,core::jeJED_BitmapFontBlock::FontKerning)
		TempKerning->Code1 = 'T';
		TempKerning->Code2 = 'e';
		TempKerning->X = -2;
		TempKerning->Y = 0;
		Font->GetKerningList().push_back(TempKerning);

		Iter = Font->GetCharsList().begin();
		for(u16 X=0;X<16*12;X++)
			Iter++;

		u16 lol = 1040;
		for(u16 X=16*12;X<16*16;X++)
		{
			core::jeJED_BitmapFontBlock::FontChar * TempChar = *Iter;


			core::jeJED_BitmapFontBlock::FontChar * TempChar2 = NULL;
			JENEW(TempChar2,core::jeJED_BitmapFontBlock::FontChar)

			memcpy(TempChar2,TempChar,sizeof(core::jeJED_BitmapFontBlock::FontChar));

			TempChar2->Code = lol++;

			JELOG(TempChar2->Code)

			Font->GetCharsList().push_back(TempChar2);

			Iter++;
		}

		Root->AddChildren(Font);
		Font->Drop();

		core::IBuffer * WriteBuffer = core::GetFileSystem()->WriteFile("TestFont.jed");
		core::GetJEDManager()->Save(WriteBuffer,Root);
		WriteBuffer->Drop();

		Root->Drop();

	}

	namespace app
	{
		//void LS(jeStringc Name,video::IRender * Ren)
		//{
		//	//JE_MESHRESOURCE(K?"TestAlpha":"TestDesu")
		//	//TestAst

		//	media::jeSharedMesh * SM = NULL;
		//	JE_MESHRESOURCE_SHARED_GRAB(SM,JE_MESHRESOURCE(Name),Ren)

		//	core::IBuffer * WB = core::GetFileSystem()->WriteFile((Name+jeStringc(".jed")).c_str());
		//	scene::GetMeshLoader()->SaveMesh(WB,SM->GetMesh(),scene::MF_JED);
		//	WB->Drop();


		//	JE_MESHRESOURCE_SHARED_DROP(SM,Ren)
		//}

		void Test()
		{
			core::ISerializeStream * SerializeStream = core::CreateSerializeStream();

			core::jeMemoryBuffer * MemoryBuffer = NULL;
			JENEW(MemoryBuffer,core::jeMemoryBuffer)

			//SerializeStream->SetLinearMode(true);
			SerializeStream->SetMode(core::SSM_SAVE);

			f32 Time = JETIME;

			const u32 SECTIONCOUNT = 500;
			const u32 VARIABLESCOUNT = 40;
			const u32 VARIABLESIZE = 2048;

			JE_SS_BEGIN(a)
			for(u32 i=0;i<SECTIONCOUNT;i++)
			{
				JE_SS_NEW(Test)
				
				for(u32 i=0;i<VARIABLESCOUNT;i++)
				{
					s32 test[VARIABLESIZE];
					JE_SS_SIZE(test,VARIABLESIZE*sizeof(s32))
				}
				JE_SS_END(Test)
			}
			JE_SS_END(a)

			SerializeStream->SaveBuffer(MemoryBuffer);

			Time = JETIME - Time;

			//JELOG(jeStringc(" TIME = ")+Time)

			s32 MemSize = SECTIONCOUNT*VARIABLESCOUNT*VARIABLESIZE*4;
			s32 MemSize2 = MemoryBuffer->GetSize();

			f32 Speed = (f32)MemSize / (Time/1000.0f);

			MemSize /= 1024*1024;
			MemSize2 /= 1024*1024;
			Speed /= 1024.0f*1024.0f;
			JELOG(jeStringc("MemSize = ")+MemSize+jeStringc(" mb"))
			JELOG(jeStringc("MemSize2 = ")+MemSize2+jeStringc(" mb"))

			JELOG(jeStringc("Save Speed = ")+(s32)Speed+jeStringc(" mb/s"))

			SerializeStream->Drop();
	
			SerializeStream = core::CreateSerializeStream();

			SerializeStream->SetLinearMode(true);
			SerializeStream->SetMode(core::SSM_LOAD);

			f32 Time2 = JETIME;

			SerializeStream->LoadBuffer(MemoryBuffer);

			JE_SS_BEGIN(a)
			JE_SS_BEGIN(Test)
			for(u32 i=0;i<SECTIONCOUNT;i++)
			{
				for(u32 i=0;i<VARIABLESCOUNT;i++)
				{
					s32  test[VARIABLESIZE];
					JE_SS_SIZE(test,VARIABLESIZE*sizeof(s32))
				}
				JE_SS_NEXT;
			}
			JE_SS_END(Test)
			JE_SS_END(a)

			Time2 = JETIME - Time2;

			//JELOG(jeStringc(" TIME = ")+Time2)

			MemSize = SECTIONCOUNT*VARIABLESCOUNT*VARIABLESIZE*4;

			Speed = (f32)MemSize / (Time2/1000.0f);

			MemSize /= 1024*1024;
			Speed /= 1024.0f*1024.0f;
			//JELOG(jeStringc("MemSize = ")+MemSize+jeStringc(" mb"))

			JELOG(jeStringc("Load Speed = ")+(s32)Speed+jeStringc(" mb/s"))


			SerializeStream->Drop();

			MemoryBuffer->Drop();
		}

		//! Constructor
		CPerspective_Game::CPerspective_Game(video::jeRenderWindow * RenderWindow)
			:CurrentRenderWindow(RenderWindow)
		{
			CurrentRenderWindow->Grab();

			//PrepareAndSaveTestFont();

			//Test();

			CreateScene();

			//LS("TestAlpha",CurrentRenderWindow->GetRender());
			//LS("TestDesu",CurrentRenderWindow->GetRender());
			//LS("TestAst",CurrentRenderWindow->GetRender());

			//Sound = JE_SOUNDRESOURCE("Test");

			//Sound->Load();

			//if(Sound->GetSound())
			//	Sound->GetSound()->Play();
			
			//SaveGameToFile("scene_save1.txt");
			//SceneManager->Drop();

			//SceneManager = scene::CreateSceneManager(CurrentRenderWindow->GetRender(),scene::BSMC_FORWARD);
			//RegisterObjects(SceneManager);
			//LoadGameFromFile("scene_save1.txt");
		}

		//! Destructor
		CPerspective_Game::~CPerspective_Game()
		{
			SceneManager->Drop();
			CurrentRenderWindow->Drop();
		}

		//! Tick
		void CPerspective_Game::Tick()
		{
			input::IKeyDriver * kdrv = CurrentRenderWindow->GetWindow()->GetKeyDriver();
			if(kdrv->IsHit(input::KC_ESCAPE))
				SetRun(false);

			if(kdrv->IsHit(input::KC_1))
			{
				JELOG("---")
				for(core::IProfiler::SectionsListType::Iterator Iter = core::GetProfiler()->GetSections().begin();Iter!=core::GetProfiler()->GetSections().end();Iter++)
					JELOG((*Iter)->Name+jeStringc(" - ")+jeStringc((*Iter)->WorkTime))
			}

		}

		//! On Update
		void CPerspective_Game::OnUpdate()
		{
			input::IKeyDriver * kdrv = CurrentRenderWindow->GetWindow()->GetKeyDriver();

			//if(kdrv->IsHit(input::KC_1))
			//{
			//	JELOG(SceneManager->GetCurrentCamera()->GetPosition().X)
			//	JELOG(SceneManager->GetCurrentCamera()->GetPosition().Y)
			//	JELOG(SceneManager->GetCurrentCamera()->GetPosition().Z)
			//	JELOG(SceneManager->GetCurrentCamera()->GetRotation().X)
			//	JELOG(SceneManager->GetCurrentCamera()->GetRotation().Y)
			//	JELOG(SceneManager->GetCurrentCamera()->GetRotation().Z)
			//}

			if(kdrv->IsHit(input::KC_2))
				CurrentRenderWindow->GetWindow()->SetFullScreen(true,jeVector2di(1600,1200));
			if(kdrv->IsHit(input::KC_3))
			{
				CurrentRenderWindow->GetWindow()->SetFullScreen(false,jeVector2di(1024,768));
				//CurrentRenderWindow->GetWindow()->SetSize(jeVector2di(1024,768));
			}

			if(kdrv->IsHit(input::KC_4))
			{
				JELOG("====")
				for(core::IProfiler::SectionsListType::Iterator Iter = core::GetProfiler()->GetSections().begin();Iter!=core::GetProfiler()->GetSections().end();Iter++)
					JELOG((*Iter)->Name + jeStringc(" : ")+jeStringc((*Iter)->WorkTime))
			}

			if(kdrv->IsHit(input::KC_8))
				SceneManager->GetCurrentCamera()->SetCameraOptions(scene::ICameraSceneNode::CameraOptions().Set2D(false,true,-1000.0f,1000.0f));
			if(kdrv->IsHit(input::KC_9))
				SceneManager->GetCurrentCamera()->SetCameraOptions(scene::ICameraSceneNode::CameraOptions().Set3D());

			//f32 DDD = 0.01f * JEDT32;
			////if(kdrv->IsDown(input::KC_T))
			////	core::GetVariables()->SetVariable("SkinA",core::GetVariables()->GetVariablef32("SkinA")-DDD);
			////if(kdrv->IsDown(input::KC_Y))
			////	core::GetVariables()->SetVariable("SkinA",core::GetVariables()->GetVariablef32("SkinA")+DDD);
			////
			//core::GetVariables()->SetVariable("SkinA",core::GetVariables()->GetVariablef32("SkinA")+DDD);

			//if(core::GetVariables()->GetVariablef32("SkinA")>7.4f)
			//	core::GetVariables()->SetVariable("SkinA",0.0f);

			////--- TODO
			//scene::IMeshSceneNode * Kuznec = static_cast<scene::IMeshSceneNode*>(SceneManager->GetNodeByName("Kuznec"));
			//Kuznec->SetAnimation(scene::IMeshSceneNode::MeshAnimation(core::GetVariables()->GetVariablef32("SkinA")));

			//if(kdrv->IsHit(input::KC_U))
			//	core::GetVariables()->SetVariable("SkinS",!core::GetVariables()->GetVariablec8("SkinS"));


			//if(kdrv->IsHit(input::KC_Z))
			//{
			//	scene::ITextSceneNode::TextOptions TxtOpt;
			//	TxtOpt.DynamicMode = !Text->GetTextOptions().DynamicMode;
			//	//TxtOpt.OriginInCenter = false;
			//	Text->SetTextOptions(TxtOpt);
			//	Text->SetText(jeStringd("Fps : ")+jeStringd((s32)core::GetFpsCounter()->GetFps()));
			//}

			SceneManager->OnUpdate();
		}

		//! On Render
		void CPerspective_Game::OnRender()
		{
			CurrentRenderWindow->GetRender()->ClearScreen(video::jeColorARGB32f(1.0f,0.2f,0.2f,0.2f));
			//CurrentRenderWindow->GetRender()->ClearScreen(video::jeColorARGB32f(1.0f,0.0f,0.607f,0.8156f));
			//CurrentRenderWindow->GetRender()->ClearScreen(video::jeColorARGB32f(0,0,0,0));
			SceneManager->OnRender();
		}

		//! Set Run
		void CPerspective_Game::SetRun(u1 Mode)
		{
			Run = Mode;
		}

		//! Return true if run
		u1 CPerspective_Game::IsRun()
		{
			return Run;
		}

		//! Create Scene
		void CPerspective_Game::CreateScene()
		{
			//#define T_ALPHASORT
			#define T_TESTMESHES

			SceneManager = scene::CreateSceneManager(CurrentRenderWindow->GetRender(),scene::BSMC_DEFERRED);

			// Register Objects
			RegisterObjects(SceneManager);

			//for(scene::ISceneManager::CompositorListType::Iterator Iter = SceneManager->GetCompositorList()->begin();Iter!=SceneManager->GetCompositorList()->end();Iter++)
			//	(*Iter)->Drop();
			//SceneManager->GetCompositorList()->clear();
			//SceneManager->GetCompositorList()->push_back(SceneManager->GetCompositorFactory()->Create("DeferredShadingCompositor"));

			// Create Camera
			Camera = SceneManager->CreateCamera();
			
			Camera->SetName("MainSceneCamera");
			//Camera->SetPosition(jeVector3df(1.1f,0.4f,0.1f));
			//Camera->SetRotation(jeVector3df(-11,143,0));
			//Camera->SetPosition(jeVector3df(0,0.5f,1));

			//Camera->SetPosition(jeVector3df(0.642129f,0.515873f,1.912502f));
			//Camera->SetRotation(jeVector3df(14.25f,-203.5f,0));

			Camera->SetPosition(jeVector3df(0.288233f,0.008113f,1.692458f));
			Camera->SetRotation(jeVector3df(-3.750000f,-223.750000f,0));

			scene::IAnimator * FpsAnim = SceneManager->GetAnimatorFactory()->Create("MouseRotateAnimator");
			Camera->AddAnimator(FpsAnim);
			FpsAnim->Drop();

			scene::IAnimator * MoveAnim = SceneManager->GetAnimatorFactory()->Create("KeyMoverAnimator");
			Camera->AddAnimator(MoveAnim);
			MoveAnim->Drop();

			SceneManager->SetCurrentCamera(Camera);

			//scene::ISpriteSceneNode * Sp = SceneManager_GUI->CreateSprite();
			//Sp->SetMaterialResource(JE_MATERIALRESOURCE("Loading"));

			// Create Light
			//scene::ILightSceneNode * LightNode = SceneManager->CreateLight();
			//LightNode->SetPosition(jeVector3df(0,3,2));
			//SceneManager->CreateDebug(LightNode);

			for(s32 i=0;i<8;i++)
			{
				scene::ILightSceneNode * LightNode2 = SceneManager->CreateLight();
				LightNode2->SetPosition(jeVector3df(2,0,0));
				//SceneManager->CreateDebug(LightNode2);

				scene::TestAnim * tanim = NULL;
				JENEW(tanim,scene::TestAnim)
				LightNode2->AddAnimator(tanim);
				tanim->Angle = i*5.0f;//67.5f;
				
				//tanim->OnUpdate();
				//LightNode2->RemoveAnimator(tanim);
				
				tanim->Drop();
			}

			// Create Debug Objects
			SceneManager->CreateDebug();
			SceneManager->CreateDebug()->SetType(scene::IDebugSceneNode::DSNT_GRID);

			#ifdef T_ALPHASORT
			{
				u1 K = false;
				s32 b = 10;
				for(s32 x=-b;x<=b;x++)
					for(s32 y=-b;y<=b;y++)
					{
						K = !K;
						scene::IMeshSceneNode * MeshNode = SceneManager->CreateMeshNode();
						MeshNode->SetMeshResource(JE_MESHRESOURCE(K?"TestAlpha":"TestDesu"));
						MeshNode->SetPosition(jeVector3df(x*0.1f,0.0f,y*0.1f)+jeVector3df(0,0.4f-0.4f,2.0f));
						MeshNode->SetRotation(jeVector3df(0,0,180));
						MeshNode->SetScale(jeVector3df(0.05f));

//							scene::jeScriptAnimator * Animator;
//							JENEW(Animator,scene::jeScriptAnimator())
//							Animator->SetScriptClassName("ScriptAnimator1");
//							MeshNode->AddAnimator(Animator);
//							Animator->Drop();


					}

				scene::IMeshSceneNode * MeshNode = SceneManager->CreateMeshNode();
				MeshNode->SetMeshResource(JE_MESHRESOURCE("TestAst"));
				MeshNode->SetPosition(jeVector3df(0.0f,0.2f,2.0f));
				MeshNode->SetScale(jeVector3df(0.001f));
			}

			#endif

			#ifdef T_TESTMESHES
			{
				scene::IMeshSceneNode * MeshNode3 = SceneManager->CreateMeshNode();
				MeshNode3->SetMeshResource(JE_MESHRESOURCE("TestB3D"));
				MeshNode3->SetScale(jeVector3df(0.01f));
				MeshNode3->SetPosition(jeVector3df(0,-0.1f,0));
				MeshNode3->SetRotation(jeVector3df(0,180,0));

				////core::GetVariables()->SetVariable("SkinS",1);
				//scene::IMeshSceneNode * Kuznec = SceneManager->CreateMeshNode();
				////Kuznec->SetMeshResource(JE_MESHRESOURCE("Kuznec"));
				////Kuznec->SetMeshResource(JE_MESHRESOURCE("TestSkin"));
				//Kuznec->SetMeshResource(JE_MESHRESOURCE("Zombie"));
				//Kuznec->SetScale(jeVector3df(0.02f));
				//Kuznec->SetName("Kuznec");

				//scene::IMeshSceneNode * MeshNodes3 = SceneManager->CreateMeshNode();
				//MeshNodes3->SetMeshResource(JE_MESHRESOURCE("Sphere"));

				//scene::ISpriteSceneNode * SP = SceneManager->CreateSprite();
				//SP->SetMaterialResource(JE_MATERIALRESOURCE("Default"));

				//MeshNode3->SetScale(jeVector3df(0.01f));
				//MeshNode3->SetPosition(jeVector3df(0,-0.1f,0));
				//MeshNode3->SetRotation(jeVector3df(0,180,0));

				//scene::IMeshSceneNode * MeshNode_Ut = SceneManager->CreateMeshNode();
				//MeshNode_Ut->SetMeshResource(JE_MESHRESOURCE("Ut3"));
				//MeshNode_Ut->SetScale(jeVector3df(0.1f));
				//MeshNode_Ut->SetRotation(jeVector3df(90,0,180));
				//MeshNode_Ut->SetPosition(jeVector3df(0,-0.3f-0.7f,0));

				//scene::IMeshSceneNode * MeshNode_x = SceneManager->CreateMeshNode();
				//MeshNode_x->SetMeshResource(JE_MESHRESOURCE("Athene"));
				//MeshNode_x->SetScale(jeVector3df(0.0006f));
				//MeshNode_x->SetPosition(jeVector3df(0,1.6f,0.0f));
				//MeshNode_x->SetRotation(jeVector3df(0,0,180));

				//scene::IMeshSceneNode * MeshNode = SceneManager->CreateMeshNode();
				//MeshNode->SetMeshResource(JE_MESHRESOURCE("TestDesu"));
				//MeshNode->SetRotation(jeVector3df(0,0,180));
			}
			#endif
		}

		//! Save Game To File
		void CPerspective_Game::SaveGameToFile(const jeStringd & FileName)
		{
			core::ISerializeStream * stream = core::CreateSerializeStream();
			stream->SetMode(core::SSM_SAVE);
			f32 TT;
			TT = JETIME;
			SceneManager->Serialize(stream);
			TT = JETIME - TT;
			JELOG(jeStringc("save serialize time : ")+TT)

			core::IFileBuffer * buf = core::GetFileSystem()->WriteFile(FileName);
			TT = JETIME;
			stream->SaveBuffer(buf);
			TT = JETIME - TT;
			JELOG(jeStringc("save buffer time : ")+TT)
			buf->Drop();
			stream->Drop();
		}

		//! Load Game From File
		void CPerspective_Game::LoadGameFromFile(const jeStringd & FileName)
		{
			core::GetVariables()->SetVariable("OpenGL_LogVersion",0);
			core::GetVariables()->SetVariable("OpenGL_LogExtensions",0);

			u1 LoadingRun = true;
			u1 WaitingLoadingContext = true;

			video::IRenderContext * RenderContext = CurrentRenderWindow->GetRender()->GetContext();

			// Deattach context
			CurrentRenderWindow->GetRender()->SetContext(NULL);

			#pragma JE_THREAD_PARALLEL JE_THREAD_FLAG_SECTIONS JE_THREAD_FLAG_NUMTHREADS(2) JE_THREAD_FLAG_SHARED(LoadingRun,WaitingLoadingContext)
			{
				// there we load our scene
				#pragma JE_THREAD_SECTION
				{
					#ifdef JE_THREADS
					
					// wait until load animation thread create context and setup it
					while(WaitingLoadingContext)
						core::GetSystem()->SystemSleep(1);
					
					#endif

					// attach main context to main render
					// it's needed because render system work with context per thread
					CurrentRenderWindow->GetRender()->SetContext(RenderContext);

					//core::GetSystem()->SystemSleep(1000);

					core::IFileBuffer * buf = core::GetFileSystem()->ReadFile(FileName);

					// Create serialize stream and attach file to stream
					core::ISerializeStream * stream = core::CreateSerializeStream();

					f32 T1 = JETIME;

					stream->LoadBuffer(buf);

					f32 TL1 = JETIME-T1;

					stream->SetMode(core::SSM_LOAD);
					stream->SetLinearMode(true);

					f32 T2 = JETIME;

					// Load scene
					SceneManager->Serialize(stream);

					f32 TL2 = JETIME-T2;

					JELOG(jeStringc("Load saved file : ")+T1)
					JELOG(jeStringc("serialize info : ")+T2)

					// Drop buffers
					buf->Drop();
					stream->Drop();

					// Deattach context
					CurrentRenderWindow->GetRender()->SetContext(NULL);

					// Finish load
					LoadingRun = false;
				}

				// there we render loading animation
				#ifdef JE_THREADS
				#pragma JE_THREAD_SECTION
				{
					video::IRender * LoadingRender = NULL;
					video::IRenderContext * LoadingRenderContext = NULL;

					// Create loading render
					LoadingRender = video::CreateRender(video::GDT_OPENGL);

					// Create loading context
					LoadingRenderContext = LoadingRender->CreateContext();
					LoadingRenderContext->SetWindow(CurrentRenderWindow->GetWindow());

					// Setup context
					LoadingRender->SetContext(LoadingRenderContext);

					// Config context
					LoadingRenderContext->SetFullWindowUse(CurrentRenderWindow->GetRenderContext()->IsFullWindowUse());
					LoadingRenderContext->SetVSyncFlag(CurrentRenderWindow->GetRenderContext()->GetVSyncFlag());

					// Loading render setup completed
					WaitingLoadingContext = false;

					// Create loading scene manager
					scene::ISceneManager * LoadingSceneManager = scene::CreateSceneManager(LoadingRender);

					// Create Camera
					scene::ICameraSceneNode * LoadingCamera = LoadingSceneManager->CreateCamera();
					LoadingCamera->SetCameraOptions(scene::ICameraSceneNode::CameraOptions().Set2D());
					LoadingSceneManager->SetCurrentCamera(LoadingCamera);

					// Create Sprite
					scene::ISpriteSceneNode * LoadingSprite = LoadingSceneManager->CreateSprite();
					LoadingSprite->SetMaterialResource(JE_MATERIALRESOURCE("Loading"));
					LoadingSprite->SetName("Loading");

					// Attach animator to sprite
					scene::jeSpriteFrameAnimator * LoadingAnimator;
					JENEW(LoadingAnimator,scene::jeSpriteFrameAnimator)
					LoadingAnimator->SetDeltaTime(200);
					LoadingSprite->AddAnimator(LoadingAnimator);
					LoadingAnimator->Drop();

					// Loop loading animation until scene will loaded
					while(LoadingRun)
					{
						LoadingRender->Begin();
						LoadingRender->ClearScreen(video::jeColorARGB8(255,0,155,208).ConvertToRange(0,255,0,1));
						LoadingSceneManager->OnUpdate();
						LoadingSceneManager->OnRender();
						LoadingRender->End();

						CurrentRenderWindow->GetDevice()->DevicePoll();
						core::GetSystem()->SystemSleep(1);
					}
			
					// Drop scene manager
					LoadingSceneManager->Drop();

					// Deattach context
					LoadingRender->SetContext(NULL);

					// Drop context
					LoadingRenderContext->SetWindow(NULL);
					LoadingRenderContext->Drop();
					LoadingRender->Drop();
				}
				#endif
			}

			// Set base context to base render
			CurrentRenderWindow->GetRender()->SetContext(RenderContext);

			// Update engine
			core::EngineTick();

			// Get camera from scene
			Camera = static_cast<scene::ICameraSceneNode*>(SceneManager->GetNodeByName("MainSceneCamera"));
		}

		//! Create Game
		IPerspective_Game * JE_GAME_FUNCTION_CALL CreateGamePerspective(video::jeRenderWindow * RenderWindow)
		{
			IPerspective_Game * Game = NULL;
			JENEW(Game,CPerspective_Game(RenderWindow))
			return Game;
		}
	}
}
